<?php

define('FILESAVER', 'defined(\'SYS_PATH\') or die(\'No direct access!\')');

/**
 * Description of system
 *
 * @author adrian
 */
final class System {

    /**
     * Nazwa kodowa
     * @var string
     */
    public static $codename = 'LONGALPHA';
    /**
     * wersja
     * @var double
     */
    public static $ver = 0.1;

    /**
     * Funkcja setup ładuje podstawowe funkcje systemu
     */
    public static function setup() {
        session_start(); //start sesji przed nagłówkami.
        header('Content-Type: text/html; charset=UTF-8'); //nagłówek kodowania.
        spl_autoload_register(array('System', 'autoload')); // no...
        //załadowanie klasy config
        require_once CORE . 'config.php';
        //załadowanie configa systemu
        Config::instance()->load_configs();

        //routing
        Event::add('router', array('Router', 'find_uri'));
                   
        //kontroler (magia)
        Event::add('controller', array('System', 'initialize'));

        //wyłączenie wszystkiego
        Event::add('shutdown', array('System', 'shutdown'));
    }

    /**
     * Funkcja ładuje automatycznie wywołane klasy
     * @param String $class
     */
    public static function autoload($class) {
        if (class_exists($class)) {
            return TRUE;
        }
        $class = strtolower($class);
        $pos = strpos($class, "_"); // pozycja pierwszej _ oznaczająca rodzaj biblioteki
        $dir = substr($class, 0, $pos);
        if (!$pos) {
            $dir = "libs";
        } else {
            if ($dir == 'controller')
                $dir = 'controllers';
            elseif ($dir == 'model')
                $dir = 'models';
            else
                echo "not found";
            //od pierwszej _ do końca
        $class = substr($class, $pos+1);
        }       
        //tutaj _ są zamieniane na / żeby można było wkładać Bardziej abstrakcyjne
        //klasy do głębszych folderów
        $class = str_replace("_", "/", $class);

        if ($filename = System::search($class, $dir)) {
            require "$filename"; //WTF?!
        } else {
            return FALSE;
        }
        return TRUE;
    }

    public static function log($message) {
        // dd-mm-YYYY::message
        $datatime = time();
        $data = date("Y-m-d", $datatime);
        $message = $data . "::" . $message;
        $logPath = DOCROOT . 'logs/' . $data . 'php';
        $file = fopen($logPath, "a");
        fwrite($file, $message);
        fclose($file);
    }

    /**
     *
     * @param string $name
     * @param string $element
     * @return mixed
     */
    public static function config($name = 'system', $element = null) {
        return Config::get_value($name, $element);
    }

    /**
     * Magia! Tutaj inicjowany jest kontroler z routera.
     */
    public static function initialize() {        
        try {
            $controller = new ReflectionClass("Controller_".ucfirst(Router::$controller));
            //nowa instancja kontrolera do wyświetlania strony:
            $controllerClass = $controller->newInstance();
            //odpalanie zdarzeń po inicjalizacji konstruktora kontrolera
            if ($controller->hasMethod(Router::$action)){
                $controller->getMethod(Router::$action)->invokeArgs($controllerClass, Router::$params);
            }
            else
                throw new ExceptionSystem("Nie istnieje taka metoda");
            Event::run('postcontroller');
        } catch (ExceptionSystem $e) {
            $e->__toString();
        } catch (ReflectionException $e) {
            echo "Metoda \"" . Router::$action . "\" nie istnieje w klasie ".Router::$controller;
        }
    }

    /**
     * Wyłacza system
     */
    public static function shutdown() {
        spl_autoload_unregister(array('System', 'autoload'));
    }

    /**
     *
     * @param string $file
     * @param string $directory
     * @param string $ext
     * @param boolean $administrator
     * @return mixed
     */
    public static function search($file, $directory = NULL, $ext = NULL, $administrator = FALSE) {
        if ($ext === null) {
            $ext = EXT;
        }
        //główne katalogi:
        $main_directories = array(MOD_PATH, COM_PATH, SYS_PATH);
        //katalogi wyszukiwawcze:
        $paths = array();
        foreach ($main_directories as $dir) {
            if ($dir == SYS_PATH) {
                $filename = $dir . $directory . '/' . $file . $ext;
                //TODO: tutaj trzeba zrobić obsługę wyjątków
                if (file_exists($filename) && is_file($filename)) {
                    return $filename;
                }                
                $filename = '';
                $directory = '';                
            } else {
                //tutaj pobierane są podkatalogi z katalogów innych niż system
                $directories = new DirectoryIterator($dir);
                foreach ($directories as $path) {
                    if ($path->isDir()) {
                        $filename = $path->getPath() ."/contents/". $directory . '/' . $file.$ext;
                        echo $filename."<br>";
                        if (is_file($filename))
                            return $filename;
                    }
                }
            }
        }
        return FALSE;
    }

}

/**
 *
 */
class ExceptionSystem extends Exception {

    /**
     *
     * @var View
     */
    private $template = 'exception';

    public function __construct($message, $code = null) {
        parent::__construct($message, $code);

        $this->template = View::factory($this->template);
        $this->template->message = $message;
    }

    public function render() {
        $this->template->render();
    }

}
?>
